Skip to content

Conversation

@cruzanstx
Copy link

@cruzanstx cruzanstx commented Jan 9, 2026

Summary

  • Fixes "Process exited unexpectedly" errors when mobile users send messages during parallel Task subagent execution with worktrees
  • Adds session path tracking so sessions created in different directories validate correctly

Problem

When running parallel Task subagents (e.g., via worktrees):

  1. Claude Code may create new sessions in different working directories (worktrees)
  2. Happy CLI detects the new session ID but validates it against the original path
  3. Session file exists in the worktree path, not the original path
  4. Validation fails and crashes

Solution

Track the path where each session was created and use that path for validation:

  • Added SessionInfo interface with id and path fields
  • sessionId getter maintains backward compatibility
  • claudeCheckSession() now accepts optional sessionPath parameter
  • Extract cwd from SDKSystemMessage during session discovery

Test plan

  • yarn build passes
  • yarn test passes (102 tests)
  • Manual test: Start Happy CLI, run parallel tasks in worktrees, verify no crashes

Generated with Claude Code via Happy

Co-Authored-By: Claude [email protected]
Co-Authored-By: Codex [email protected]

@cruzanstx
Copy link
Author

Manual Test Results

Tested the session path tracking fix with parallel Task subagents.

Test Scenario

  1. Started Happy CLI session in a test directory
  2. Ran 3 parallel Task agents with subagent_type=Explore targeting different directories
  3. Monitored for "Process exited unexpectedly" errors

Results

Check Result
Session started in test directory Pass
Parallel Task subagents executed Pass
No "Process exited unexpectedly" errors Pass
Session remained running after parallel tasks Pass
Session responsive (ready state) Pass

Verification

  • Confirmed session_id and cwd are properly tracked in logs
  • Session hook correctly captured session path
  • No crashes observed when sending messages during parallel task execution

The fix successfully prevents crashes when Task subagents operate in different working directories.

When Task subagents create sessions in different directories (e.g., worktrees),
the session validation now uses the path where the session was created rather
than the current working directory. This fixes "Process exited unexpectedly"
errors when mobile users send messages during parallel prompt execution.

Also fixes error logging - Error objects were being logged as `{}` because
JSON.stringify doesn't capture non-enumerable Error properties.

Changes:
- Add SessionInfo interface with id and path fields
- Update Session class to track session creation path
- Modify claudeCheckSession to accept optional sessionPath
- Extract cwd from SDKSystemMessage for session tracking
- Logger now properly serializes Error objects with name/message/stack
- Added getLaunchErrorInfo helper for structured error logging

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Happy <[email protected]>
@cruzanstx cruzanstx force-pushed the prompt/004-session-path-tracking-fix branch from 6e7942a to 45e32f1 Compare January 12, 2026 19:53
@cruzanstx
Copy link
Author

Update: Added error serialization fix

This PR now also includes a fix for error logging. Previously, Error objects were logged as {} because JSON.stringify(error) doesn't capture non-enumerable Error properties.

Additional changes in this update:

src/ui/logger.ts

  • Logger now properly serializes Error objects with name, message, stack, and any custom properties

src/claude/claudeRemoteLauncher.ts

  • Added getLaunchErrorInfo() helper for structured error logging
  • Captures asString fallback, name, message, code, and stack

This fixes the issue where [remote]: launch error {} appeared in logs, making debugging "Process exited unexpectedly" errors impossible.

When Claude Code crashes (e.g., from MaxFileReadTokenExceededError), Happy
now:
- Tracks consecutive crashes and limits to 3 retries
- Shows informative messages: "Claude process crashed, restarting... (attempt 1/3)"
- Stops gracefully after max retries instead of infinite loop
- Resets crash counter on successful completion

This improves UX when Claude hits edge cases like reading files that exceed
the 25K token limit, which can crash the process instead of being handled
gracefully.

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Happy <[email protected]>
@cruzanstx
Copy link
Author

Update: Added crash recovery with retry limit

This PR now includes automatic crash recovery when Claude Code crashes unexpectedly.

New behavior:

Before:

  • Claude crashes → "Process exited unexpectedly" → infinite retry loop

After:

  • Claude crashes → "Claude process crashed, restarting... (attempt 1/3)"
  • Max 3 retries before stopping gracefully
  • Counter resets on successful message exchange

Use case:

When Claude hits edge cases like MaxFileReadTokenExceededError (reading files >25K tokens), the Claude Code process can crash instead of handling it gracefully. This improvement prevents infinite loops and gives users clear feedback about what's happening.

Files changed:

  • src/claude/claudeRemoteLauncher.ts - Added consecutiveCrashes counter and improved error messages

When Claude crashes and recovers, automatically resend the last
message that was being processed. This prevents users from having
to manually resend their message after a crash.

- Track lastSentMessage for crash recovery resend
- Clear immediately after resend (one-time only, prevents loops)
- Show "Your message will be resent." in recovery notification
- Reset lastSentMessage on successful completion

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <[email protected]>
Co-Authored-By: Happy <[email protected]>
@cruzanstx
Copy link
Author

New commit: Auto-resend message on crash recovery

Added 5d55225 which automatically resends the last message when Claude crashes and recovers.

How it works:

  1. lastSentMessage tracks the message being sent to Claude
  2. On crash recovery, nextMessage() checks if there's a message to resend
  3. If yes, resends it once only (clears immediately to prevent loops)
  4. User sees: "Claude process crashed, restarting... (attempt 1/3) Your message will be resent."

Verified in production - logs show it working:

[17:00:09.862] [remote]: resending last message after crash recovery (one-time)
[17:00:09.904] message: "Claude process crashed, restarting... (attempt 1/3) Your message will be resent."

This completes the crash recovery feature - users no longer need to manually resend their message after a crash.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant